package asignacionDeRevisores;
import static org.mockito.Mockito.*;
import java.util.*;

import org.junit.Before;
import org.junit.Test;

import asignacionDeRevisores.AsignacionPorAlta;

import static org.junit.Assert.*;


import callForPapers.CallForPaper;
import callForPapers.Paper;
import sistema.*;

/**
 * @author Publico
 * JavaDoc CTRL+ALT+J
 */


public class AsignacionDeRevisoresTestCase {
	
	// Sección 1 Extras
	private AsignacionPorAlta asignador = new AsignacionPorAlta(); 
	private CallForPaper mCfp;
	private Paper unPaper, dosPaper, tresPaper, cuatroPaper;
	private int max = 10;
	private int i = max;
	private List<Paper> papers = new ArrayList<Paper>();
	private Set<Paper> devuelvePapers = new HashSet<Paper>();
	
	// Sección 2 Usuarios
	private Usuario mUsuarioAntiguo, mUsuarioViejo, mUsuarioActual, mUsuarioFuturo,
			mUsuarioNoRepetido, mUnaExperiencia,mDosExperiencias,mSinExperiencia,
			unUsuario; 
	private Usuario dosUsuario;
	private Usuario tresUsuario;
	private Usuario cutreUsuario;
	
	// Sección 3 Lista de usuarios
	private List<Usuario> enOrden = new ArrayList<Usuario>();
	private List<Usuario> aOrdenar = new ArrayList<Usuario>();
	private List<Usuario> desRevisores = new ArrayList<Usuario>();
	private List<Usuario> unosRevisores = new ArrayList<Usuario>();
	private List<Usuario> pequeno = new ArrayList<Usuario>();
	private List<Usuario> chico = new ArrayList<Usuario>();
	private List<Usuario> grande = new ArrayList<Usuario>();
	private List<Usuario> gde = new ArrayList<Usuario>();
	private List<Usuario> listaConUno = new ArrayList<Usuario>();
	private List<Usuario> listaConDos = new ArrayList<Usuario>();
	private List<Usuario> listaDeRevisores3 = new ArrayList<Usuario>();
	private List<Usuario> revisores = new ArrayList<Usuario>();
	private Set<Usuario> devuelveRevisores = new HashSet<Usuario>();
	
	// Sección 4 Calendar
	private Calendar ahora = Calendar.getInstance();
	private Calendar manana = Calendar.getInstance();
	private Calendar ayer = Calendar.getInstance();
	private Calendar antiguo = Calendar.getInstance();
	
	// Sección 5 Areas
	private AreaDeInteres unArea = new AreaDeInteres("Matematica");
	private AreaDeInteres otraArea = new AreaDeInteres("Ciencias Sociales");
	private AreaDeInteres ultimaArea = new AreaDeInteres("Filosofia");
	private AreaDeInteres noArea = new AreaDeInteres("Singularidad, Kirk Cpt.");
	
	// Sección 6 Lista/Set de areas
	private Set<AreaDeInteres> areas = new HashSet<AreaDeInteres>(); // tiene que devolver un set
	private Set<AreaDeInteres> unaAreas = new HashSet<AreaDeInteres>(); // tiene que devolver un set
	private Set<AreaDeInteres> sinAreas = new HashSet<AreaDeInteres>(); // tiene que devolver un set
	private List<AreaDeInteres> areasPaper = new ArrayList<AreaDeInteres>();
	private List<AreaDeInteres> desairesPaper = new ArrayList<AreaDeInteres>();
	private List<AreaDeInteres> filtrarExpertos = new ArrayList<AreaDeInteres>();
	private Set<AreaDeInteres> asignarAreas = new HashSet<AreaDeInteres>();
	private Set<AreaDeInteres> asignaAreas = new HashSet<AreaDeInteres>();
	private Set<AreaDeInteres> noAsignaAreas = new HashSet<AreaDeInteres>();
	

	
	@Before
	public void setUp(){
		// Sección 6 Lista/Set de areas
				areas.add(unArea);
				areas.add(otraArea);
				unaAreas.add(unArea);
				areasPaper.addAll(areas);
				areasPaper.add(this.ultimaArea);
				desairesPaper.add(noArea);
				filtrarExpertos.add(unArea);
				filtrarExpertos.add(otraArea);
				filtrarExpertos.add(ultimaArea);
				filtrarExpertos.add(noArea);
				asignarAreas.add(unArea);
				asignarAreas.add(otraArea);
				asignarAreas.add(ultimaArea);
				asignarAreas.add(noArea);
				asignaAreas.add(unArea);
				asignaAreas.add(otraArea);
				asignaAreas.add(ultimaArea);
				noAsignaAreas.add(noArea);
		// Sección 4 Calendar
				antiguo.set(1009, Calendar.JUNE, 01);
				ayer.set(2010, Calendar.JUNE, 01);
				ahora.set(2011, Calendar.JUNE, 01);
				manana.set(2012, Calendar.JUNE, 01);
		// Sección 2 Usuarios
				mUsuarioAntiguo = mock(Usuario.class);								
					when(mUsuarioAntiguo.getFecha()).thenReturn(antiguo);
				mUsuarioViejo = mock(Usuario.class);
					when(mUsuarioAntiguo.getFecha()).thenReturn(ayer);
				mUsuarioActual = mock(Usuario.class);
					when(mUsuarioAntiguo.getFecha()).thenReturn(ahora);
				mUsuarioFuturo = mock(Usuario.class);
					when(mUsuarioAntiguo.getFecha()).thenReturn(manana);
					
				unUsuario = new Usuario("algo", "algo", "algo", "algo", "algo", ahora, asignarAreas);
				dosUsuario = new Usuario("algo", "algo", "algo", "algo", "algo", ahora, asignaAreas);
				tresUsuario = new Usuario("algo", "algo", "algo", "algo", "algo", ahora, areas);
				cutreUsuario = new Usuario("algo", "algo", "algo", "algo", "algo", ahora, noAsignaAreas);
				//mock(Usuario.class);
				mDosExperiencias = mock(Usuario.class);
					when(mDosExperiencias.getAreasDeInteres()).thenReturn(areas);
				mUnaExperiencia = mock(Usuario.class);
					when(mUnaExperiencia.getAreasDeInteres()).thenReturn(unaAreas);
				mSinExperiencia = mock(Usuario.class);
					when(mUnaExperiencia.getAreasDeInteres()).thenReturn(sinAreas);
				mUsuarioNoRepetido = mock(Usuario.class);
		
		// Sección 3	Lista de usuarios
		
		enOrden.add(mUsuarioAntiguo);
		enOrden.add(mUsuarioViejo);
		enOrden.add(mUsuarioActual);
		enOrden.add(mUsuarioFuturo);
		aOrdenar.add(mUsuarioActual);
		aOrdenar.add(mUsuarioFuturo);
		aOrdenar.add(mUsuarioAntiguo);
		aOrdenar.add(mUsuarioViejo);
		desRevisores.add(mUsuarioNoRepetido);
		unosRevisores.add(mUsuarioNoRepetido);
		chico.addAll(aOrdenar);
			chico.remove(mUsuarioViejo);
		pequeno.addAll(aOrdenar);
			pequeno.remove(mUsuarioViejo);
		grande.addAll(aOrdenar);
		gde.addAll(aOrdenar);
		listaConUno.add(mUsuarioActual);
		listaConDos.add(mUsuarioActual);
		listaConDos.add(mUsuarioFuturo);
		listaDeRevisores3.add(unUsuario);
		listaDeRevisores3.add(mUnaExperiencia);
		listaDeRevisores3.add(mDosExperiencias);
		revisores.add(unUsuario);
		revisores.add(dosUsuario);
		revisores.add(tresUsuario);
		revisores.add(cutreUsuario);
		devuelveRevisores.addAll(aOrdenar);
		
		// Sección 1 Extras
		unPaper = new Paper(unUsuario, areas ); // Usuario y 4 areas
		dosPaper = new Paper(dosUsuario, asignarAreas );
		tresPaper = new Paper(tresUsuario, asignaAreas );
		cuatroPaper = new Paper(cutreUsuario, noAsignaAreas );
		papers.add(unPaper);
		papers.add(dosPaper);
		papers.add(tresPaper);
		papers.add(cuatroPaper);
		
		mCfp = mock(CallForPaper.class);
		when(mCfp.getAreasDeInteres()).thenReturn(areas);
		// Retorno una lista de usuarios:
		when(mCfp.getRevisores()).thenReturn(devuelveRevisores);
		// Retorno una lista de papers:
		when(mCfp.getPapers()).thenReturn( devuelvePapers);
		
		
			
		
		
		
			// FIN DEL testSETUP
			// FIN DEL testSETUP
			// FIN DEL testSETUP
		}
	
	/**
	 * Corroboro que la lista que devuelve el metodo contiene los mismos elementos que el cfp
	 */
	@Test
		public void testARObtenerListaDeRevisores(){
			
			assertTrue((this.asignador.obtenerListaDeRevisores(this.mCfp)).containsAll(devuelveRevisores));
			
		}
	/**
	 * Corroboro que la lista que devuelve el metodo contiene los mismos elementos que el cfp
	 */
	@Test
		public void testARObtenerListaDePapers(){
			
			assertTrue((this.asignador.obtenerListaDePapers(this.mCfp)).containsAll(devuelvePapers));
			
		}
		
	@Test	
		public void testARTieneAlMenos1AreaEnComun(){
			assertTrue(this.asignador.tieneAlMenos1AreaEnComun(this.areasPaper, this.areas));
			assertFalse(this.asignador.tieneAlMenos1AreaEnComun(this.desairesPaper, this.areas));
		}
	@Test
		public void testARQuitarRevisoresRepetidos(){
						
			// El comando de abajo debera devolver una lista de usuarios con un elemento. A eso 
			// le pido el tamaño.
		// (a,b,c) quitar (a,b,c,d) = 0
			int tamano = this.asignador.quitarRevisoresRepetidos(chico, grande).size();
			assertEquals(tamano, 0); // Si a una lista le saco todo, se queda sin nada.
		// (a,b,c,d) quitar (a,b,c) = d
			int tamano2 = this.asignador.quitarRevisoresRepetidos(gde, pequeno).size();
			assertEquals(tamano2, 1); 	// Si no le saco todo, queda la diferencia
										// en este caso 1.
		}
	@Test	
		public void testARCompletarListaRevisoresAlAzar(){
			//public List<Usuario> completarListaRevisoresAlAzar(List<Usuario> revisores, List<Usuario> revisoresFiltrados)
			int cantUno = this.asignador.completarListaRevisoresAlAzar(aOrdenar, listaConUno).size();
			assertEquals(cantUno, 3);
			assertEquals(this.asignador.completarListaRevisoresAlAzar(enOrden, listaConDos).size(), 3);
			assertTrue(this.asignador.completarListaRevisoresAlAzar(enOrden, listaConDos).size() != 2);
		}
	@Test	
		public void testAREsExperto(){
			assertFalse(asignador.esExperto(unPaper, mUnaExperiencia));
			assertTrue(asignador.esExperto(unPaper, mDosExperiencias));
			assertFalse(asignador.esExperto(unPaper, mSinExperiencia));
		}
	@Test	
		public void testARFiltrarRevisoresExpertos(){
			//List<Usuario> filtrarRevisoresExpertos(List<Usuario> revisores, unPaper)
			int igualADos = this.asignador.filtrarRevisoresExpertos(listaDeRevisores3, unPaper).size();
			assertEquals(igualADos, 2);
		}
	@Test		
		public void testARChequearContador(){
			// chequearContador(int indice, int maximo)
			// si i = max --> 0
			assertEquals(asignador.chequearContador(i, max), 0);
			// si i < max --> i++
			i = 0;
			assertEquals(asignador.chequearContador(i, max), 1);
		}
	@Test
		public void testARAsignarPapersARevisores(){
		//asignarPapersARevisores(List<Usuario> revisores, List<Paper> listaDePapers)
		asignador.asignarPapersARevisores(revisores, papers);
		int numero = revisores.get(0).getPapersARevisar().size();
		assertTrue( numero != 0);
		int num = papers.get(1).getRevisores().size();
		assertTrue(num < 4);
		assertTrue(num > 2);
		
	}
			
}

